package com.cuixichang.minimalism.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cuixichang.minimalism.acl.RelevanceDesign;
import com.cuixichang.minimalism.basal.base.Result;
import com.cuixichang.minimalism.basal.enums.DefaultNumberEnum;
import com.cuixichang.minimalism.basal.enums.IsEnableEnum;
import com.cuixichang.minimalism.basal.utils.TreeUtil;
import com.cuixichang.minimalism.core.security.userdetails.CredentialDetail;
import com.cuixichang.minimalism.core.security.utils.SecurityBeanUtil;
import com.cuixichang.minimalism.domain.IMenuCommandService;
import com.cuixichang.minimalism.transfer.dto.IMenuDTO;
import com.cuixichang.minimalism.transfer.factory.IMenuAssembler;
import com.cuixichang.minimalism.transfer.page.IMenuPageRequest;
import com.cuixichang.minimalism.transfer.page.IMenuRequest;
import com.cuixichang.minimalism.transfer.vo.IMenuVO;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import com.cuixichang.minimalism.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统菜单表表控制层
 *
 * @author cuixichang
 * @date 2024-12-01
 */
@Api(tags = "系统菜单表对象功能接口")
@RestController
@RequestMapping("menu")
@RequiredArgsConstructor
public class IMenuController {

    @Autowired
    private IMenuService iMenuService;
    @Autowired
    private IMenuCommandService iMenuCommandService;
    @Autowired
    private RelevanceDesign relevanceDesign;

    @GetMapping("/signboard/{systemCode}")
    @ApiOperation(value = "查询菜单分组信息")
    public Result<List<String>> getMenuSignboard(@PathVariable String systemCode){
        CredentialDetail credentialDetail = SecurityBeanUtil.getCredentialDetail();
        return Result.ok("查询菜单分组信息完成",iMenuCommandService.getMenuSignboard(systemCode, credentialDetail));
    }

    @PostMapping("/info")
    @ApiOperation(value = "创建菜单基本信息")
    public Result<IMenuVO> insert(@RequestBody IMenuRequest request) {
        IMenuDTO iMenuDTO = IMenuAssembler.INSTANCT.convertDto(request);
        CredentialDetail credentialDetail = SecurityBeanUtil.getCredentialDetail();
        iMenuDTO.setCreateLoginId(Objects.nonNull(credentialDetail)?credentialDetail.getLoginId(): DefaultNumberEnum.Zero.getCode());
        IMenuDTO insert = iMenuService.insert(iMenuDTO);
        return Result.ok("菜单信息创建成功", IMenuAssembler.INSTANCT.convertVo(insert));
    }

    @DeleteMapping("/info/{systemCode}/{id}")
    @ApiOperation(value = "删除菜单基本信息通过ID")
    public Result<Boolean> deleteById(@PathVariable Long id, @PathVariable("systemCode") String systemCode){
        return Result.ok("删除菜单完成", iMenuCommandService.deleteById(id,systemCode, SecurityBeanUtil.getCredentialDetail()));
    }

    @PutMapping("/info/{systemCode}/{id}")
    @ApiOperation(value = "编辑菜单基本信息通过ID")
    public Result<Boolean> updateById(@PathVariable Long id, @PathVariable("systemCode") String systemCode,@RequestBody IMenuRequest request){
        IMenuDTO iMenuDTO = IMenuAssembler.INSTANCT.convertDto(request);
        iMenuDTO.setId(id);
        iMenuDTO.setCreateSystemCode(systemCode);
        return Result.ok("编辑菜单基本信息完成",iMenuCommandService.updateById(iMenuDTO,SecurityBeanUtil.getCredentialDetail()));
    }


    @GetMapping("/info/{systemCode}/{id}")
    @ApiOperation(value = "查询菜单基本信息通过ID")
    public Result<IMenuVO> selectById(@PathVariable("id") Long id, @PathVariable("systemCode") String systemCode){
        IMenuDTO menu = iMenuCommandService.selectByIdHasPreCheck(id, systemCode, SecurityBeanUtil.getCredentialDetail());
        return Result.ok("查询菜单基本信息完成",IMenuAssembler.INSTANCT.convertVo(menu));
    }

    @GetMapping("/page")
    @ApiOperation(value = "查询用户可操作的菜单集合信息")
    public Result<Page<IMenuVO>> searchPageByConditional(IMenuPageRequest request){
        IMenuDTO iMenuDTO = IMenuAssembler.INSTANCT.convertDto(request);
        Page<IMenuDTO> iMenuPage = iMenuCommandService.searchPageByConditional(iMenuDTO, request.getPageNo(), request.getPageSize()
                ,SecurityBeanUtil.getCredentialDetail());
        Page<IMenuVO> iMenuVOPage = new Page<>(iMenuPage.getCurrent(), iMenuPage.getSize(), iMenuPage.getTotal());
        List<IMenuDTO> records = iMenuPage.getRecords();
        Map<Long, String> parentNames = new HashMap<>(records.size());
        if(!CollectionUtils.isEmpty(records)){
            List<Long> parentIds = records.stream().map(IMenuDTO::getParentId).distinct().collect(Collectors.toList());
            parentNames.putAll(iMenuService.selectByIds(parentIds).stream().collect(Collectors.toMap(IMenuDTO::getId, IMenuDTO::getMenuName)));
        }
        iMenuVOPage.setRecords(records.stream().map(IMenuAssembler.INSTANCT::convertVo)
                .peek(menu -> menu.setMenuParentName(parentNames.get(menu.getParentId()))).collect(Collectors.toList()));
        return Result.ok("查询菜单列表完成",iMenuVOPage);
    }

    @GetMapping("/tree/{systemCode}/{signboard}")
    @ApiOperation(value = "查询用户绑定的菜单集合信息")
    public Result<List<IMenuVO>> searchTreeMenus(@PathVariable String signboard,
                                                 @PathVariable("systemCode") String systemCode){
        CredentialDetail credentialDetail = SecurityBeanUtil.getCredentialDetail();
        List<IMenuDTO> iMenus = iMenuCommandService.searchTreeMenus(systemCode, signboard, credentialDetail);
        List<IMenuVO> iMenuVOS = TreeUtil.streamToTree2(iMenus, IMenuAssembler.INSTANCT::convertVo,
                Long.parseLong(String.valueOf(DefaultNumberEnum.Zero.getCode())), IMenuVO::getId, IMenuVO::getParentId, IMenuVO::setChildren,
                Comparator.comparing(IMenuVO::getSort).thenComparing(IMenuVO::getUpdateTime));
        return Result.ok("查询绑定菜单列表完成",iMenuVOS);
    }

    @GetMapping("/overt/{systemCode}/{signboard}")
    @ApiOperation(value = "查询开放菜单集合信息(仅限查询绑定游客角色的菜单)无需登录认证")
    public Result<List<IMenuVO>> searchOvertTreeMenus(@PathVariable String signboard,
                                                      @PathVariable("systemCode") String systemCode){
        List<IMenuDTO> iMenus = iMenuCommandService.searchOvertTreeMenus(systemCode, signboard);
        List<IMenuVO> iMenuVOS = TreeUtil.streamToTree2(iMenus, IMenuAssembler.INSTANCT::convertVo,
                DefaultNumberEnum.Zero.getCode(), IMenuVO::getId, IMenuVO::getParentId, IMenuVO::setChildren,
                Comparator.comparing(IMenuVO::getSort).thenComparing(IMenuVO::getUpdateTime));
        return Result.ok("查询绑定菜单列表完成",iMenuVOS);
    }

    @GetMapping("/role/{bindingStatus}/{roleId}")
    @ApiOperation(value = "角色已绑定/允许绑定菜单查询")
    public Result<Page<IMenuVO>> roleBindingMenus(@PathVariable("bindingStatus") String bindingStatus,
                                                  @PathVariable("roleId") Long relationId,
                                                  IMenuPageRequest request) {
        IMenuDTO dto = IMenuAssembler.INSTANCT.convertDto(request);
        CredentialDetail credentialDetail = SecurityBeanUtil.getCredentialDetail();
        Page<IMenuDTO> page = Optional.ofNullable(bindingStatus).filter(code -> IsEnableEnum.YES.getCode().toString().equals(code)).map(
                code -> iMenuCommandService.roleHasBindingMenus(dto, request.getPageNo(), request.getPageSize(), relationId, credentialDetail)
        ).orElseGet(() -> iMenuCommandService.roleUnBindingMenus(dto, request.getPageNo(), request.getPageSize(), relationId, credentialDetail));
        Page<IMenuVO> result = new Page(page.getCurrent(),page.getSize(),page.getTotal());
        List<IMenuDTO> records = page.getRecords();
        Map<Long, String> parentNames = new HashMap<>(records.size());
        if(!CollectionUtils.isEmpty(records)){
            List<Long> parentIds = records.stream().map(IMenuDTO::getParentId).distinct().collect(Collectors.toList());
            parentNames.putAll(iMenuService.selectByIds(parentIds).stream().collect(Collectors.toMap(IMenuDTO::getId, IMenuDTO::getMenuName)));
        }
        result.setRecords(records.stream().map(IMenuAssembler.INSTANCT::convertVo)
                .peek(menu -> menu.setMenuParentName(parentNames.get(menu.getParentId()))).collect(Collectors.toList()));
        return Result.ok("查询成功",result);
    }

    @PostMapping("/role/{bindingStatus}/{menuId}/{roleId}")
    @ApiOperation(value = "权限绑定（解绑）角色")
    public Result<Boolean> roleBindingStatus(@PathVariable("bindingStatus") String bindingStatus,
                                             @PathVariable("roleId") Long roleId,
                                             @PathVariable("menuId") Long menuId){
        return Result.ok("操作成功",relevanceDesign.roleMenuBindingStatus(roleId, menuId, IsEnableEnum.YES.getCode().toString().equals(bindingStatus),
                SecurityBeanUtil.getCredentialDetail()));
    }
}
